﻿using System;
using System.IO;
using System.Threading;

namespace Infrastructure.CrossCutting.Configuration
{
    public abstract class FileBasedConfigSource : ConfigSection, IConfigSource
    {
        protected readonly string configFilePath;
        private readonly FileSystemWatcher fileWatcher;

        protected FileBasedConfigSource(string name, bool enableWatching)
        {
            configFilePath = name;
            Init();
            Load();
            if (enableWatching)
            {
                var fi = new FileInfo(configFilePath);
                fileWatcher = new FileSystemWatcher
                {
                    Path = fi.Directory.FullName,
                    Filter = "*.xml",
                    EnableRaisingEvents = true
                };
                fileWatcher.Changed += FileWatcherChanged;
                //fileWatcher.Created += FileWatcherChanged;
                //fileWatcher.Deleted += FileWatcherChanged;
                //fileWatcher.Renamed += new FileSystemEventHandler(FileWatcherChanged);
            }
        }

        void FileWatcherChanged(object sender, FileSystemEventArgs e)
        {
            // the object is selfupdating
            try
            {
                fileWatcher.EnableRaisingEvents = false;
                Thread.Sleep(1000);
                Init();
                Load();
                if (OnConfigSourceChanged != null)
                    OnConfigSourceChanged(this, e);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                fileWatcher.EnableRaisingEvents = true;
            }
        }

        #region Implementation of IConfigSource

        public event EventHandler OnConfigSourceChanged;

        /// <summary>
        /// Name of the source. This cane be the file path. 
        /// </summary>
        /// <value>The source path.</value>
        public string SourcePath
        {
            get { return configFilePath; }
        }

        public abstract void Init();

        /// <summary>
        /// Load the config settings from the underlying datasource. 
        /// </summary>
        public abstract void Load();

        /// <summary>
        /// Save the config settings to the underlying datasource. 
        /// </summary>
        public abstract void Save();

        public abstract void ChangeConfigItem(string configItemName, object value);

        #endregion
    }

}
